from datetime import datetime
from docutils.core import publish_parts

from sqlalchemy import Table, ForeignKey, Column, Integer, Unicode, DateTime, Boolean
from sqlalchemy.orm import relation, backref

from papyrus.model.meta import Base

# many-to-many relation between articles and labels
articles_labels = Table('articles_labels', Base.metadata,
    Column('article_id', None, ForeignKey('articles.id')),
    Column('label_id', None, ForeignKey('labels.id')),
)


class Article(Base):
    """An article object."""

    __tablename__ = 'articles'

    id = Column(Integer, primary_key=True)
    title = Column(Unicode, nullable=False)
    body = Column(Unicode, nullable=False)
    is_published = Column(Boolean, default=False)
    allow_comments = Column(Boolean, default=True)
    creation_date = Column(DateTime, default=datetime.now)
    author_id = Column(None, ForeignKey('users.id'), nullable=False)

    labels = relation('Label', backref="articles", secondary=articles_labels, cascade="save-update")
    comments = relation('Comment', backref="article", cascade="all, delete-orphan")

    def __repr__(self):
        return "<%s %r, %r>" % (self.__class__.__name__, self.id, self.title[:10])

    def to_rss(self):
        """Return the article as a string in RSS format."""
        raise NotImplementedError

    def to_atom(self):
        """Return the article as a string in ATOM format."""
        raise NotImplementedError

    def to_html(self):
        """Return the article's body as HTML"""
        parts = publish_parts(source=self.body, writer_name='html')
        return parts['html_body']

    def to_json(self):
        """Return the article as a string in JSON format."""
        raise NotImplementedError


class Comment(Base):
    """A comment object."""

    __tablename__ = 'comments'

    id = Column(Integer, primary_key=True)
    author = Column(Unicode, nullable=False)
    message = Column(Unicode, nullable=False)
    creation_date = Column(DateTime, default=datetime.now)
    is_published = Column(Boolean, default=False)
    article_id = Column(None, ForeignKey('articles.id'), nullable=False)

    def __repr__(self):
        return "<%s %r, %r>" % (self.__class__.__name__, self.id, self.message[:10])


class Label(Base):
    """A label object."""

    __tablename__ = 'labels'

    id = Column(Integer, primary_key=True)
    name = Column(Unicode, nullable=False, unique=True)

    def __repr__(self):
        return "<%s %r>" % (self.__class__.__name__, self.name)
